package app.myproject.action.notification;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomCollectionEditor;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;

import app.myproject.dao.NotificationDAOImpl;
import app.myproject.model.NotificationVO;
import app.myproject.util.CustomeKeyEditor;
import app.myproject.validator.NotificationValidator;


@Controller
@RequestMapping("/notification")
@SessionAttributes(value={"notification"})
public class NotificationController {

	@Resource 
	NotificationValidator validator;
	
	@Autowired
	public NotificationController(NotificationValidator notificationValidator){
		this.validator = notificationValidator;
	}
	
	@ModelAttribute("statusList")
	public Map<String,String> populateStatusList() {
 
		//Data referencing for web framework checkboxes
		Map<String,String> statusMap = new LinkedHashMap<String,String>();
		statusMap.put("1", "Started");
		statusMap.put("2", "Completed");
		statusMap.put("0", "None");
 
		return statusMap;
	}
	
	@InitBinder
	protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
	
	    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	    dateFormat.setLenient(false);

	    binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
	    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
	    binder.registerCustomEditor(List.class, new CustomCollectionEditor(List.class));
	    binder.registerCustomEditor(com.google.appengine.api.datastore.Key.class, new CustomeKeyEditor());

	}
	
	protected boolean validate(NotificationVO notification, BindingResult result) {
		validator.validate(notification, result);
		if (result.hasErrors()) {
			printErrorLog(result);
			return false;
		}
		return true;
	}
	
	protected void printErrorLog(BindingResult result) {
		System.out.println("errors");
		for (ObjectError error:result.getAllErrors()) {
			System.out.println(error.getDefaultMessage());
		}
	}
	
	@RequestMapping(method = RequestMethod.GET)
	public String forward(ModelMap model) {
		return "forward:list";
	}
	
	@RequestMapping(value = "/add", method = RequestMethod.GET)
	public String toAdd(ModelMap model) {
		System.out.println("toAdd");
		
		NotificationDAOImpl dao = new NotificationDAOImpl();
		NotificationVO notification = dao.create();
		model.addAttribute("notification",notification);
		
		return "notification/add";
	}

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public ModelAndView add(@ModelAttribute("notification") NotificationVO notification, BindingResult result, SessionStatus status) {
		System.out.println("add");
				
		if (validate(notification, result)) {
			notification.setCreated(new Date());
			NotificationDAOImpl dao = new NotificationDAOImpl();
			dao.save(notification);
			status.setComplete();			
		}
		else {
			return new ModelAndView("notification/add");
		}
		
		return new ModelAndView("redirect:/notification/list");
	}

	@RequestMapping(value = "/update/{encodedKey}", method = RequestMethod.GET)
	public String toEdit(@PathVariable String encodedKey, ModelMap model) {
		System.out.println("toEdit");
		
		NotificationDAOImpl dao = new NotificationDAOImpl();
		NotificationVO notification = dao.find(encodedKey);
		model.addAttribute("notification", notification);
		
		return "notification/update";

	}

	@RequestMapping(value = "/update/{encodedKey}", method = RequestMethod.POST)
	public ModelAndView edit(@PathVariable String encodedKey, @ModelAttribute("notification") NotificationVO notification, BindingResult result, SessionStatus status) {
		System.out.println("edit");
		
		if (validate(notification, result)) {
			NotificationDAOImpl dao = new NotificationDAOImpl();
			dao.update(notification);
			status.setComplete();
		} 
		else {
			return new ModelAndView("notification/update");			
		}

		return new ModelAndView("redirect:/notification/list");

	}

	@RequestMapping(value = "/delete/{encodedKey}", method = RequestMethod.GET)
	public ModelAndView delete(@PathVariable String encodedKey, ModelMap model) {
		System.out.println("delete");
		
		NotificationDAOImpl dao = new NotificationDAOImpl();
		dao.deleteById(encodedKey);

		return new ModelAndView("redirect:/notification/list");

	}

	// get all notifications
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String list(ModelMap model) {

		System.out.println("list");
		
		NotificationDAOImpl dao = new NotificationDAOImpl();
		List<NotificationVO> list = dao.list();	
		model.addAttribute("notificationList", list);
		
		System.out.println("result: " + list.size());

		return "notification/list";

	}

}